﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using Common.Utilities;
using ZedGraph;

namespace Workflows.Components.Entities.MasterData
{
    public partial class FieldInteractionViewer : Form
    {
        public FieldInteractionViewer()
        {
            InitializeComponent();
        }

        private void btn_BrowseProfile_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg=new OpenFileDialog();
            dlg.Filter =
                "Dependency files(*.dep)|*.dep|Xml files(*.xml)|*.xml|Excel files(*.xlsx)|*.xlsx|All files(*.*)|*.*";
            if(dlg.ShowDialog()==System.Windows.Forms.DialogResult.OK)
            {
                this.txt_DependencyFile.Text = dlg.FileName;
                this.PopulateDependencyFields(dlg.FileName);
            }
        }

        private void PopulateDependencyFields(string filePath)
        {
            XmlDocument xDoc = new XmlDocument();
            xDoc.Load(filePath);
            XmlNode root = xDoc.DocumentElement;
            string determinantField = XmlDataUtil.GetAttributeValue(root, "Determinant", "");
            this.txt_DetField.Text = determinantField;

            this.cbo_DepField.Items.Clear();
            XmlNodeList depNodes = root.SelectNodes("DependentField");
            if(depNodes !=null && depNodes.Count>0)
            {
                foreach(XmlNode depNode in depNodes)
                {
                    string dependentField = XmlDataUtil.GetAttributeValue(depNode, "FieldName", "");
                    this.cbo_DepField.Items.Add(dependentField);
                }
            }
        }

        private void btn_Refresh_Click(object sender, EventArgs e)
        {
            if(this.cbo_DepField.SelectedIndex>=0)
            {
                XmlDocument xDoc = new XmlDocument();
                xDoc.Load(this.txt_DependencyFile.Text);
                XmlNode root = xDoc.DocumentElement;
                XmlNodeList depNodes = root.SelectNodes("DependentField");
                if (depNodes != null && depNodes.Count > 0)
                {
                    foreach (XmlNode depNode in depNodes)
                    {
                        string dependentField = XmlDataUtil.GetAttributeValue(depNode, "FieldName", "");
                        if(this.cbo_DepField.Text==dependentField)
                        {
                            double correspondence = double.Parse(XmlDataUtil.GetAttributeValue(depNode, "Correspondence", "0"));
                            double correlation = double.Parse(XmlDataUtil.GetAttributeValue(depNode, "Correlation", "0"));
                            double r = double.Parse(XmlDataUtil.GetAttributeValue(depNode, "RScore", "0"));
                            double r2 = double.Parse(XmlDataUtil.GetAttributeValue(depNode, "R2Score", "0"));
                            this.grp_Chart.Text = string.Format(
                                "Correspondence={0}, Correlation={1}, R={2}, R2={3}",
                                Math.Round(correspondence, 4),
                                Math.Round(correlation, 4),
                                Math.Round(r, 4),
                                Math.Round(r2, 4));

                            break;
                        }
                    }
                }
                try
                {
                    string connStr = XmlDataUtil.GetAttributeValue(root, "ConnStr", "");
                    string schemaName = XmlDataUtil.GetAttributeValue(root, "SchemaName", "");
                    string tblName = XmlDataUtil.GetAttributeValue(root, "TblName", "");
                    string sql = XmlDataUtil.GetAttributeValue(root, "Sql", "");
                    PointPairList xyValues = this.GetXYValues(connStr, schemaName, tblName, sql, this.txt_DetField.Text,
                                                              this.cbo_DepField.Text);
                    this.DisplayScatterPlot(xyValues, this.cbo_DepField.Text, this.txt_DetField.Text,
                                            this.ck_DepLog.Checked,
                                            this.ck_DetLog.Checked);
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        private PointPairList GetXYValues(string connStr, 
            string schemaName, string tblName, string sql, 
            string detName, string depName)
        {
            DataTable dt = null;
            if(!string.IsNullOrEmpty(sql))
            {
                string sql1 = string.Format("select {0},{1} from ({2}) t",
                                            detName, depName, sql);
                dt = DbUtil.GetTableDataBySQL(connStr, "Output", sql1);
            }
            else
            {
                string sql1 = string.Format("select {0},{1} from {2}.[{3}]",
                                            detName, depName, schemaName, tblName);
                dt = DbUtil.GetTableDataBySQL(connStr, "Output", sql1);
            }
            SqlDbType detDataType = FieldDataType.ToSqlDbType(
                SimpleDataTypeUtil.ToSimpleDataType(dt.Columns[detName].DataType));
            SqlDbType depDataType = FieldDataType.ToSqlDbType(
                SimpleDataTypeUtil.ToSimpleDataType(dt.Columns[depName].DataType));
            PointPairList xyValues = new PointPairList();
            
            foreach(DataRow dr in dt.Rows)
            {
                if (dr[detName] != null && dr[detName] != DBNull.Value &&
                    dr[depName] != null && dr[depName] != DBNull.Value)
                {
                    double? y = null;
                    double? x = null;
                    if(FieldDataType.IsNumber(detDataType))
                        y = double.Parse(dr[detName].ToString());
                    else if (FieldDataType.IsDateTime(detDataType))
                        y = DateTime.Now.Year - DateTime.Parse(dr[detName].ToString()).Year;
                    if(FieldDataType.IsNumber(depDataType))
                        x = double.Parse(dr[depName].ToString());
                    else if (FieldDataType.IsDateTime(depDataType))
                        x = DateTime.Now.Year - DateTime.Parse(dr[depName].ToString()).Year;
                    if (x.HasValue && y.HasValue)
                        xyValues.Add(x.Value, y.Value);
                }
            }
            return xyValues;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="xyValues">dep value -> det value</param>
        /// <param name="xLabel">dependent field</param>
        /// <param name="yLabel">determinant field</param>
        /// <param name="xLog"></param>
        /// <param name="yLog"></param>
        private void DisplayScatterPlot(
            PointPairList xyValues, string xLabel, string yLabel,
            bool xLog, bool yLog)
        {
            GraphPane myPane = this.zedGraph.GraphPane;
            myPane.CurveList.Clear();
            myPane.GraphObjList.Clear();

            // Set the titles
            myPane.Title.Text = string.Format("{0} vs. {1}", xLabel, yLabel);
            myPane.XAxis.Title.Text = xLabel;
            if (xLog)
                myPane.XAxis.Title.Text = xLabel + " (log)";
            myPane.YAxis.Title.Text = yLabel;
            if (yLog)
                myPane.YAxis.Title.Text = yLabel + " (log)";

            // Populate a PointPairList with a log-based function and some random variability
            PointPairList list = new PointPairList();
            double maxY = 0;
            foreach(PointPair pt in xyValues)
            {
                double xVal = pt.X;
                if (xLog)
                    xVal = Math.Log(xVal);
                double yVal = pt.Y;
                if (yLog)
                    yVal = Math.Log(yVal);
                list.Add(xVal, yVal);
                if (yVal > maxY)
                    maxY = yVal;
            }

            // Add the curve
            LineItem myCurve = myPane.AddCurve("Correlation Plot", list, Color.Black, SymbolType.Diamond);
            // Don't display the line (This makes a scatter plot)
            myCurve.Line.IsVisible = false;
            // Hide the symbol outline
            myCurve.Symbol.Border.IsVisible = false;
            // Fill the symbol interior with color
            myCurve.Symbol.Fill = new Fill(Color.Firebrick);

            // Fill the background of the chart rect and pane
            myPane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45.0f);
            myPane.Fill = new Fill(Color.White, Color.SlateGray, 45.0f);
            this.zedGraph.AxisChange();
            myPane.YAxis.Scale.Max = maxY + myPane.YAxis.Scale.MajorStep;

            this.zedGraph.AxisChange();
            this.zedGraph.Refresh();
        }
    }
}
